{
 "cells": [
  {
   "cell_type": "raw",
   "metadata": {
    "vscode": {
     "languageId": "raw"
    }
   },
   "source": [
    "---\n",
    "title: Life of a value\n",
    "sidebar_position: 2\n",
    "description: An explanation of when and how Mojo creates values.\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The life of a value in Mojo begins when a variable is initialized and continues\n",
    "up until the value is last used, at which point Mojo destroys it. This page\n",
    "describes how every value in Mojo is created, copied, and moved. (The next\n",
    "page describes [how values are\n",
    "destroyed](/mojo/manual/lifecycle/death.html).)\n",
    "\n",
    "All data types in Mojo—including basic types in the standard library such as\n",
    "[`Bool`](/mojo/stdlib/builtin/bool/Bool),\n",
    "[`Int`](/mojo/stdlib/builtin/int/Int), and\n",
    "[`String`](/mojo/stdlib/builtin/string/String), up to complex types such\n",
    "as [`SIMD`](/mojo/stdlib/builtin/simd/SIMD) and\n",
    "[`object`](/mojo/stdlib/builtin/object/object)—are defined as a\n",
    "[struct](/mojo/manual/structs.html). This means the creation and\n",
    "destruction of any piece of data follows the same lifecycle rules, and you can\n",
    "define your own data types that work exactly the same way.\n",
    "\n",
    "Mojo structs don't get any default lifecycle methods, such as a\n",
    "constructor, copy constructor, or move constructor. That means you can create\n",
    "a struct without a constructor, but then you can't instantiate it, and it\n",
    "would be useful only as a sort of namespace for static methods. For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct NoInstances:\n",
    "    var state: Int\n",
    "\n",
    "    @staticmethod\n",
    "    fn print_hello():\n",
    "        print(\"Hello world!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Without a constructor, this cannot be instantiated, so it has no lifecycle. The\n",
    "`state` field is also useless because it cannot be initialized (Mojo structs do\n",
    "not support default field values—you must initialize them in a constructor).\n",
    "\n",
    "So the only thing you can do is call the static method:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello world!\n"
     ]
    }
   ],
   "source": [
    "NoInstances.print_hello()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Constructor\n",
    "\n",
    "To create an instance of a Mojo type, it needs the `__init__()` constructor\n",
    "method. The main responsibility of the constructor is to initialize all fields.\n",
    "For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct MyPet:\n",
    "    var name: String\n",
    "    var age: Int\n",
    "\n",
    "    fn __init__(inout self, name: String, age: Int):\n",
    "        self.name = name\n",
    "        self.age = age"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can create an instance:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "var mine = MyPet(\"Loki\", 4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "An instance of `MyPet` can also be\n",
    "[borrowed](/mojo/manual/values/ownership.html#immutable-arguments-borrowed)\n",
    "and destroyed, but it currently can't be copied or moved.\n",
    "\n",
    "We believe this is a good default starting point, because there are no built-in\n",
    "lifecycle events and no surprise behaviors. You—the type author—must\n",
    "explicitly decide whether and how the type can be copied or moved, by\n",
    "implementing the copy and move constructors.\n",
    "\n",
    ":::note\n",
    "\n",
    "Mojo does not require a destructor to destroy an object. As long as\n",
    "all fields in the struct are destructible (every type in the standard library\n",
    "is destructible, except for\n",
    "[pointers](/mojo/stdlib/memory/unsafe.html)), then Mojo knows how to destroy\n",
    "the type when its lifetime ends. We'll discuss that more in [Death of a\n",
    "value](/mojo/manual/lifecycle/death.html).\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Overloading the constructor\n",
    "\n",
    "Like any other function/method, you can\n",
    "[overload](/mojo/manual/functions.html#overloaded-functions) the\n",
    "`__init__()` constructor to initialize the object with different arguments. For\n",
    "example, you might want a default constructor that sets some default values and\n",
    "takes no arguments, and then additional constructors that accept more arguments.\n",
    "\n",
    "Just be aware that, in order to modify any fields, each constructor must\n",
    "declare the `self` argument with the [`inout`\n",
    "convention](/mojo/manual/values/ownership.html#mutable-arguments-inout). If you\n",
    "want to call one constructor from another, you simply call upon that\n",
    "constructor as you would externally (you don't need to pass `self`).\n",
    "\n",
    "For example, here's how you can delegate work from an overloaded constructor:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct MyPet:\n",
    "    var name: String\n",
    "    var age: Int\n",
    "\n",
    "    fn __init__(inout self):\n",
    "        self.name = \"\"\n",
    "        self.age = 0\n",
    "\n",
    "    fn __init__(inout self, name: String):\n",
    "        self = MyPet()\n",
    "        self.name = name"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Field initialization\n",
    "\n",
    "Notice in the previous example that, by the end of each constructor, all fields\n",
    "must be initialized. That's the only requirement in the constructor.\n",
    "\n",
    "In fact, the `__init__()` constructor is smart enough to treat the `self`\n",
    "object as fully initialized even before the constructor is finished, as long\n",
    "as all fields are initialized. For example, this constructor can pass around\n",
    "`self` as soon as all fields are initialized:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn use(arg: MyPet):\n",
    "    pass\n",
    "\n",
    "struct MyPet:\n",
    "    var name: String\n",
    "    var age: Int\n",
    "\n",
    "    fn __init__(inout self, name: String, age: Int, cond: Bool):\n",
    "        self.name = name\n",
    "        if cond:\n",
    "            self.age = age\n",
    "            use(self)  # Safe to use immediately!\n",
    "\n",
    "        self.age = age\n",
    "        use(self)  # Safe to use immediately!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Constructors and implicit conversion\n",
    "\n",
    "Mojo supports implicit conversion from one type to another. Implicit conversion\n",
    "can happen when one of the following occurs:\n",
    "\n",
    "- You assign a value of one type to a variable with a different type.\n",
    "- You pass a value of one type to a function that requires a different type.\n",
    "\n",
    "In both cases, implicit conversion is supported when the target type\n",
    "defines a constructor that takes a single required, non-keyword argument of the\n",
    "source type. For example:\n",
    "\n",
    "```mojo\n",
    "var a = Source()\n",
    "var b: Target = a\n",
    "```\n",
    "\n",
    "Mojo implicitly converts the `Source` value in `a` to a `Target` value if \n",
    "`Target` defines a matching constructor like this:\n",
    "\n",
    "```mojo\n",
    "struct Target:\n",
    "  fn __init__(inout self, s: Source): ...\n",
    "```\n",
    "\n",
    "With implicit conversion, the assignment above is essentially identical to:\n",
    "\n",
    "```mojo\n",
    "var b = Target(a)\n",
    "```\n",
    "\n",
    "The constructor used for implicit conversion can take optional arguments, so\n",
    "the following constructor would also support implicit conversion from `Source`\n",
    "to `Target`:\n",
    "\n",
    "```mojo\n",
    "struct Target:\n",
    "  fn __init__(inout self, s: Source, reverse: Bool = False): ...\n",
    "```\n",
    "\n",
    "Implicit conversion also occurs if the type doesn't declare its own constructor,\n",
    "but instead uses the [`@value` decorator](#value-decorator), _and_ the type\n",
    "has only one field. That's because Mojo automatically creates a member-wise\n",
    "constructor for each field, and when there is only one field, that synthesized\n",
    "constructor works exactly like a conversion constructor. For example, this\n",
    "type also can convert a `Source` value to a `Target` value:\n",
    "\n",
    "```mojo\n",
    "@value\n",
    "struct Target:\n",
    "  var s: Source\n",
    "```\n",
    "\n",
    "Implicit conversion can fail if Mojo can't unambiguously match the conversion to\n",
    "a constructor. For example, if the target type has two overloaded constructors\n",
    "that take different types, and each of those types supports an implicit\n",
    "conversion from the source type, the compiler has two equally-valid paths to \n",
    "convert the values:\n",
    "\n",
    "```mojo\n",
    "struct A: \n",
    "  fn __init__(inout self, s: Source): ...\n",
    "\n",
    "struct B: \n",
    "  fn __init__(inout self, s: Source): ...\n",
    "\n",
    "struct Target:\n",
    "  fn __init__(inout self, a: A): ...\n",
    "  fn __init__(inout self, b: B): ...\n",
    "\n",
    "# Fails\n",
    "var t = Target(Source())\n",
    "```\n",
    "\n",
    "In this case, removing either one of the target type's constructors will fix the\n",
    "problem.\n",
    "\n",
    "If you want to define a single-argument constructor, but you **don't** want\n",
    "the types to implicitly convert, you can define the constructor with a \n",
    "[keyword-only argument](/mojo/manual/functions#positional-only-and-keyword-only-arguments):\n",
    "\n",
    "```mojo\n",
    "struct Target:\n",
    "  # does not support implicit conversion\n",
    "  fn __init__(inout self, *, source: Source): ...\n",
    "\n",
    "# the constructor must be called with a keyword\n",
    "var t = Target(source=a)\n",
    "```\n",
    "\n",
    ":::note\n",
    "\n",
    "In the future we intend to provide a more explicit method of declaring whether\n",
    "a constructor should support implicit conversion.\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Copy constructor\n",
    "\n",
    "When Mojo encounters an assignment operator (`=`), it tries to make a copy of\n",
    "the right-side value by calling upon that type's copy constructor: the\n",
    "`__copyinit__()` method. Thus, it's the responsibility of the type author to\n",
    "implement `__copyinit__()` so it returns a copy of the value.\n",
    "\n",
    "For example, the `MyPet` type above does not have a copy constructor,\n",
    "so this code fails to compile:\n",
    "\n",
    "```mojo\n",
    "var mine = MyPet(\"Loki\", 4)\n",
    "var yours = mine  # This requires a copy, but MyPet has no copy constructor\n",
    "```\n",
    "\n",
    "To make it work, we need to add the copy constructor, like\n",
    "this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct MyPet:\n",
    "    var name: String\n",
    "    var age: Int\n",
    "\n",
    "    fn __init__(inout self, name: String, age: Int):\n",
    "        self.name = name\n",
    "        self.age = age\n",
    "\n",
    "    fn __copyinit__(inout self, existing: Self):\n",
    "        self.name = existing.name\n",
    "        self.age = existing.age"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ":::note\n",
    "\n",
    "`Self` (capital \"S\") is an alias for the current type name\n",
    "(`MyPet`, in this example). Using this alias is a best practice to avoid any\n",
    "mistakes when referring to the current struct name.\n",
    "\n",
    "Also, notice that the `existing` argument in `__copyinit__()` is immutable\n",
    "because the default [argument\n",
    "convention](/mojo/manual/values/ownership.html#argument-conventions) in an `fn`\n",
    "function is `borrowed`—this is a good thing because this function should not\n",
    "modify the contents of the value being copied.\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now this code works to make a copy:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "var mine = MyPet(\"Loki\", 4)\n",
    "var yours = mine"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "What makes Mojo's copy behavior different, compared to other languages, is that\n",
    "`__copyinit__()` is designed to perform a deep copy of all fields in the type\n",
    "(as per [value semantics](/mojo/manual/values/value-semantics.html)). That is,\n",
    "it copies heap-allocated values, rather than just copying the pointer.\n",
    "\n",
    "However, the Mojo compiler doesn't enforce this, so it's the type author's\n",
    "responsibility to implement `__copyinit__()` with value semantics. For example,\n",
    "here's a new `HeapArray` type that performs a deep copy in the copy constructor:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct HeapArray:\n",
    "    var data: Pointer[Int]\n",
    "    var size: Int\n",
    "    var cap: Int\n",
    "\n",
    "    fn __init__(inout self, size: Int, val: Int):\n",
    "        self.size = size\n",
    "        self.cap = size * 2\n",
    "        self.data = Pointer[Int].alloc(self.cap)\n",
    "        for i in range(self.size):\n",
    "            self.data.store(i, val)\n",
    "\n",
    "    fn __copyinit__(inout self, existing: Self):\n",
    "        # Deep-copy the existing value\n",
    "        self.size = existing.size\n",
    "        self.cap = existing.cap\n",
    "        self.data = Pointer[Int].alloc(self.cap)\n",
    "        for i in range(self.size):\n",
    "            self.data.store(i, existing.data.load(i))\n",
    "        # The lifetime of `existing` continues unchanged\n",
    "\n",
    "    fn __del__(owned self):\n",
    "        # We must free the heap-allocated data, but\n",
    "        # Mojo knows how to destroy the other fields\n",
    "        self.data.free()\n",
    "\n",
    "    fn append(inout self, val: Int):\n",
    "        # Update the array for demo purposes\n",
    "        if self.size < self.cap:\n",
    "            self.data.store(self.size, val)\n",
    "            self.size += 1\n",
    "        else:\n",
    "            print(\"Out of bounds\")\n",
    "\n",
    "    fn dump(self):\n",
    "        # Print the array contents for demo purposes\n",
    "        print(\"[\", end=\"\")\n",
    "        for i in range(self.size):\n",
    "            if i > 0:\n",
    "                print(\", \", end=\"\")\n",
    "            print(self.data.load(i), end=\"\")\n",
    "        print(\"]\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice that `__copyinit__()` does not copy the `Pointer` value (doing so would\n",
    "make the copied value refer to the same `data` memory address as the original\n",
    "value, which is a shallow copy). Instead, we initialize a new `Pointer` to\n",
    "allocate a new block of memory, and then copy over all the heap-allocated\n",
    "values (this is a deep copy).\n",
    "\n",
    "Thus, when we copy an instance of `HeapArray`, each copy has its own value on\n",
    "the heap, so changes to one value do not affect the other, as shown here:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn copies():\n",
    "    var a = HeapArray(2, 1)\n",
    "    var b = a    # Calls the copy constructor\n",
    "    a.dump()     # Prints [1, 1]\n",
    "    b.dump()     # Prints [1, 1]\n",
    "\n",
    "    b.append(2)  # Changes the copied data\n",
    "    b.dump()     # Prints [1, 1, 2]\n",
    "    a.dump()     # Prints [1, 1] (the original did not change)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ":::note\n",
    "\n",
    "In `HeapArray`, we must use the `__del__()` destructor to free the\n",
    "heap-allocated data when the `HeapArray` lifetime ends, but Mojo automatically\n",
    "destroys all other fields when their respective lifetimes end. We'll discuss\n",
    "this destructor more in [Death of a value](/mojo/manual/lifecycle/death.html).\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If your type doesn't use any pointers for heap-allocated data, then writing the\n",
    "constructor and copy constructor is all boilerplate code that you shouldn't\n",
    "have to write. For most structs that don't manage memory explicitly, you can \n",
    "just add the [`@value` decorator](/mojo/manual/decorators/value.html) to your\n",
    "struct definition and Mojo will synthesize the `__init__()`, `__copyinit__()`,\n",
    "and `__moveinit__()` methods.\n",
    "\n",
    ":::note\n",
    "\n",
    "Mojo also calls upon the copy constructor when a value is passed to a\n",
    "function that takes the argument as\n",
    "[`owned`](/mojo/manual/values/ownership.html#transfer-arguments-owned-and)\n",
    "_and_ when the lifetime of the given value does _not_ end at that point. If the\n",
    "lifetime of the value does end there (usually indicated with the transfer\n",
    "operator `^`), then Mojo instead invokes the move constructor.\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Move constructor\n",
    "\n",
    "Although copying values provides predictable behavior that matches Mojo's\n",
    "[value semantics](/mojo/manual/values/value-semantics.html), copying some data\n",
    "types can be a significant hit on performance. If you're familiar with\n",
    "reference semantics, then the solution here might seem clear: instead of making\n",
    "a copy when passing a value, share the value as a reference. And if the\n",
    "original variable is no longer needed, nullify the original to avoid any\n",
    "double-free or use-after-free errors. That's generally known as a move\n",
    "operation: the memory block holding the data remains the same (the memory does\n",
    "not actually move), but the pointer to that memory moves to a new variable.\n",
    "\n",
    "To support moving a value, implement the `__moveinit__()` method. The \n",
    "`__moveinit__()` method performs a consuming move: it [transfers\n",
    "ownership](/mojo/manual/values/ownership.html#transfer-arguments-owned-and)\n",
    "of a value from one variable to another when the original variable's lifetime\n",
    "ends (also called a \"destructive move\").\n",
    "\n",
    ":::note\n",
    "\n",
    "A move constructor is **not required** to transfer ownership of a\n",
    "value. Unlike in Rust, transferring ownership is not always a move operation;\n",
    "the move constructors are only part of the implementation for how Mojo\n",
    "transfers ownership of a value. You can learn more in the section about\n",
    "[ownership\n",
    "transfer](/mojo/manual/values/ownership.html#transfer-arguments-owned-and).\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When a move occurs, Mojo immediately invalidates the original\n",
    "variable, preventing any access to it and disabling its destructor. Invalidating\n",
    "the original variable is important to avoid memory errors on heap-allocated\n",
    "data, such as use-after-free and double-free errors.\n",
    "\n",
    "Here's how to add the move constructor to the `HeapArray` example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct HeapArray:\n",
    "    var data: Pointer[Int]\n",
    "    var size: Int\n",
    "\n",
    "    fn __init__(inout self, size: Int, val: Int):\n",
    "        self.size = size\n",
    "        self.data = Pointer[Int].alloc(self.size)\n",
    "        for i in range(self.size):\n",
    "            self.data.store(i, val)\n",
    "\n",
    "    fn __copyinit__(inout self, existing: Self):\n",
    "        # Deep-copy the existing value\n",
    "        self.size = existing.size\n",
    "        self.data = Pointer[Int].alloc(self.size)\n",
    "        for i in range(self.size):\n",
    "            self.data.store(i, existing.data.load(i))\n",
    "\n",
    "    fn __moveinit__(inout self, owned existing: Self):\n",
    "        print(\"move\")\n",
    "        # Shallow copy the existing value\n",
    "        self.size = existing.size\n",
    "        self.data = existing.data\n",
    "        # Then the lifetime of `existing` ends here, but\n",
    "        # Mojo does NOT call its destructor\n",
    "\n",
    "    fn __del__(owned self):\n",
    "        self.data.free()\n",
    "\n",
    "    fn dump(self):\n",
    "        print(\"[\", end=\"\")\n",
    "        for i in range(self.size):\n",
    "            if i > 0:\n",
    "                print(\", \", end=\"\")\n",
    "            print(self.data.load(i), end=\"\")\n",
    "        print(\"]\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The critical feature of `__moveinit__()` is that it takes the incoming value as\n",
    "`owned`, meaning this method gets unique ownership of the value. Moreover,\n",
    "because this is a dunder method that Mojo calls only when performing a move \n",
    "(during ownership transfer), the `existing` argument is guaranteed to be a \n",
    "mutable reference to the original value, _not a copy_ (unlike other methods that\n",
    "may declare an argument as `owned`, but might receive the value as a copy if the\n",
    "method is called without the [`^` transfer\n",
    "operator](/mojo/manual/values/ownership.html#transfer-arguments-owned-and)).\n",
    "That is, Mojo calls this move constructor _only_ when the original variable's\n",
    "lifetime actually ends at the point of transfer.\n",
    "\n",
    "Here's an example showing how to invoke the move constructor for `HeapArray`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "fn moves():\n",
    "    var a = HeapArray(3, 1)\n",
    "\n",
    "    a.dump()   # Prints [1, 1, 1]\n",
    "\n",
    "    var b = a^ # Prints \"move\"; the lifetime of `a` ends here\n",
    "\n",
    "    b.dump()   # Prints [1, 1, 1]\n",
    "    #a.dump()  # ERROR: use of uninitialized value 'a'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice that `__moveinit__()` performs a shallow copy of the\n",
    "existing field values (it copies the pointer, instead of allocating new memory\n",
    "on the heap), which is what makes it useful for types with heap-allocated\n",
    "values that are expensive to copy.\n",
    "\n",
    "To go further and ensure your type can never be copied, you can make it\n",
    "\"move-only\" by implementing `__moveinit__()` and _excluding_ `__copyinit__()`.\n",
    "A move-only type can be passed to other variables and passed into functions\n",
    "with any argument convention (`borrowed`, `inout`, and `owned`)—the only catch\n",
    "is that you must use the `^` transfer operator to end the lifetime of a\n",
    "move-only type when assigning it to a new variable or when passing it as an\n",
    "`owned` argument."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ":::note\n",
    "\n",
    "For types without heap-allocated fields, you get no real benefit from\n",
    "the move constructor. Making copies of simple data types on the stack, like\n",
    "integers, floats, and booleans, is very cheap. Yet, if you allow your type to\n",
    "be copied, then there's generally no reason to disallow moves, so you can\n",
    "synthesize both constructors by adding the [`@value`\n",
    "decorator](/mojo/manual/decorators/value.html).\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Simple value types {#value-decorator}\n",
    "\n",
    "Because copy and move constructors are opt-in, Mojo provides great control for\n",
    "exotic usecases (such as for atomic values that should never be copied or\n",
    "moved), but most structs are simple aggregations of other types that should be\n",
    "easily copied and moved, and we don't want to write a lot of boilerplate\n",
    "constructors for those simple value types.\n",
    "\n",
    "To solve this, Mojo provides the [`@value`\n",
    "decorator](/mojo/manual/decorators/value.html), which synthesizes the\n",
    "boilerplate code for the `__init__()`, `__copyinit__()`, and `__moveinit__()`\n",
    "methods.\n",
    "\n",
    "For example, consider a simple struct like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "@value\n",
    "struct MyPet:\n",
    "    var name: String\n",
    "    var age: Int"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Mojo sees the `@value` decorator and notices that you don't have a member-wise\n",
    "initializer (a constructor with arguments for each field), a copy constructor,\n",
    "or a move constructor, so it synthesizes them for you. The result is as if you\n",
    "had actually written this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct MyPet:\n",
    "    var name: String\n",
    "    var age: Int\n",
    "\n",
    "    fn __init__(inout self, owned name: String, age: Int):\n",
    "        self.name = name^\n",
    "        self.age = age\n",
    "\n",
    "    fn __copyinit__(inout self, existing: Self):\n",
    "        self.name = existing.name\n",
    "        self.age = existing.age\n",
    "\n",
    "    fn __moveinit__(inout self, owned existing: Self):\n",
    "        self.name = existing.name^\n",
    "        self.age = existing.age"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Mojo synthesizes each lifecycle method only when it doesn't exist, so\n",
    "you can use `@value` and still define your own versions to override the default\n",
    "behavior. For example, it is fairly common to use the default member-wise and\n",
    "move constructor, but create a custom copy constructor. Another common pattern\n",
    "is to use `@value` to create a member-wise constructor, and add overloads that\n",
    "take different sets of arguments. For example, if  you want to create\n",
    "a `MyPet` struct without specifying an age, you could add an overloaded\n",
    "constructor:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@value\n",
    "struct MyPet:\n",
    "    var name: String\n",
    "    var age: Int\n",
    "\n",
    "    fn __init__(inout self, owned name: String):\n",
    "        self.name = name^\n",
    "        self.age = 0\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that this overloaded constructor **doesn't** prevent the `@value` decorator\n",
    "from synthesizing the member-wise constructor. To override this default\n",
    "constructor, you'd need to add a constructor with the same signature as the\n",
    "default member-wise constructor.\n",
    "\n",
    "Something you can see in this code that we didn't mention yet is that the\n",
    "`__init__()` method takes all arguments as `owned`, because the constructor\n",
    "must take ownership to store each value. This is a useful micro-optimization\n",
    "and enables the use of move-only types. Trivial types like `Int` are also\n",
    "passed as `owned`, but because ownership doesn't mean anything for integers, we\n",
    "can elide that declaration and the transfer operator (`^`) for simplicity. The\n",
    "transfer operator is also just a formality in this case, because, even if it's\n",
    "not used with `self.name = name^`, the Mojo compiler will notice that `name` is\n",
    "last used here and convert this assignment into a move, instead of a\n",
    "copy+delete.\n",
    "\n",
    ":::note\n",
    "\n",
    "If your type contains any move-only fields, Mojo will not generate\n",
    "the copy constructor because it cannot copy those fields. Further, the `@value`\n",
    "decorator won't work at all if any of your members are neither copyable nor\n",
    "movable. For example, if you have something like `Atomic` in your struct, then\n",
    "it probably isn't a true value type, and you don't want the copy/move\n",
    "constructors anyway.\n",
    "\n",
    "Also notice that the `MyPet` struct above doesn't include the `__del__()`\n",
    "destructor (the `@value` decorator does not synthesize this), because Mojo\n",
    "doesn't need it to destroy fields, as discussed in [Death of a\n",
    "value](/mojo/manual/lifecycle/death.html)\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Trivial types\n",
    "\n",
    "So far, we've talked about values that live in memory, which means they have an\n",
    "identity (an address) that can be passed around among functions (passed \"by\n",
    "reference\"). This is great for most types, and it's a safe default for large\n",
    "objects with expensive copy operations. However, it's inefficient for tiny\n",
    "things like a single integer or floating point number. We call these types\n",
    "\"trivial\" because they are just \"bags of bits\" that should be copied, moved,\n",
    "and destroyed without invoking any custom lifecycle methods.\n",
    "\n",
    "Trivial types are the most common types that surround us, and from a language\n",
    "perspective, Mojo doesn’t need special support for these written in a struct.\n",
    "Usually, these values are so tiny that they should be passed around in CPU\n",
    "registers, not indirectly through memory.\n",
    "\n",
    "As such, Mojo provides a struct decorator to declare these types of values:\n",
    "`@register_passable(\"trivial\")`. This decorator tells Mojo that the type should\n",
    "be copyable and movable but that it has no user-defined logic (no lifecycle\n",
    "methods) for doing this. It also tells Mojo to pass the value in CPU registers\n",
    "whenever possible, which has clear performance benefits.\n",
    "\n",
    "You'll see this decorator on types like `Int` in the standard library:\n",
    "\n",
    "```mojo\n",
    "@register_passable(\"trivial\")\n",
    "struct Int:\n",
    "    var value: __mlir_type.index\n",
    "\n",
    "    fn __init__(value: __mlir_type.index) -> Int:\n",
    "        return Self {value: value}\n",
    "    ...\n",
    "```\n",
    "\n",
    "We expect to use this decorator pervasively on Mojo standard library types, but\n",
    "it is safe to ignore for general application-level code.\n",
    "\n",
    "For more information, see the [`@register_passable`\n",
    "documentation](/mojo/manual/decorators/register-passable.html).\n",
    "\n",
    ":::note TODO\n",
    "\n",
    "This decorator is due for reconsideration.  Lack of custom\n",
    "copy/move/destroy logic and \"passability in a register\" are orthogonal concerns\n",
    "and should be split.  This former logic should be subsumed into a more general\n",
    "`@value(\"trivial\")` decorator, which is orthogonal from `@register_passable`.\n",
    "\n",
    ":::"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Mojo",
   "language": "mojo",
   "name": "mojo-jupyter-kernel"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "mojo"
   },
   "file_extension": ".mojo",
   "mimetype": "text/x-mojo",
   "name": "mojo"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
